package org.ainlolcat.ainscience.statistics.handlers.fitting.functions;

import org.apache.commons.math.optimization.fitting.ParametricRealFunction;

/**
* @author ainlolcat
*         Date: 5/9/13
*/
public class ZeroBasedGaussFunction implements ParametricRealFunction {

    //(A/(w*Math.sqrt(Math.PI/2)))*Math.exp(-2 * Math.pow(dx, 2) / (Math.pow(w, 2)));
    //1 - A
    //2 - w
    //3 - x0
    public double value(double x, double[] parameters) {
        double A = parameters[0];
        double w = parameters[1];
        double x0 = parameters[2];
        return A/(w*Math.sqrt(Math.PI/2))*
                        Math.exp(-2 * Math.pow((x-x0), 2) / (Math.pow(w, 2)));
    }

    public double[] gradient(double x, double[] doubles) {
        double[] gradientVector = new double[doubles.length];
        double A = doubles[0];
        double w = doubles[1];
        double x0 = doubles[2];
        double dx = x0-x;
        double EXP_VALUE = Math.exp(-2 * Math.pow(dx, 2) / (Math.pow(w, 2)));      //exp(-2*dx^2/w^2)
        double OVER_W_PI_SQUARED = 1 /(w*Math.sqrt(Math.PI/2));                    //1/[w*sqrt(PI)]
        double A_OVER_W_PI_SQUARED = A*OVER_W_PI_SQUARED;                          //A/[w*sqrt(PI)]

        gradientVector[0] = OVER_W_PI_SQUARED * EXP_VALUE;                                  //dF/dA
        gradientVector[1] =                                                                 //dF/dw
                (
                        (-1)*A/(Math.pow(w,2)*Math.sqrt(Math.PI/2))
                                +
                                A_OVER_W_PI_SQUARED * (-2*dx*dx)*(-2/Math.pow(w,3))
                )*
                        EXP_VALUE;
        gradientVector[2] =                                                                 //dF/dx0
                A_OVER_W_PI_SQUARED
                        *
                        (-2/Math.pow(w,2))*(-2*dx)
                        *
                        EXP_VALUE;
        return gradientVector;
    }
}
